package utils.binary.impl;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import utils.binary.BytesSlices;
import utils.binary.io.BytesInputStream;
import utils.io.NumberMask;

/**
 * @author Zhou Yifan
 */
public class FixedBytesSliceArray implements BytesSlices {

    private byte[] dataBytes;

    private int totalSize;

    private int dataOffset;

    private int itemCount;

    private int itemSize;

    /**
     * @param dataBytes  数据
     * @param totalSize  初始的偏移量
     * @param dataOffset 数据的起始偏移量
     * @param itemCount  数据片段的总数
     * @param itemSize   单个数据片段的大小
     */
    @Contract(pure = true)
    private FixedBytesSliceArray(byte @NotNull [] dataBytes, int totalSize, int dataOffset, int itemCount, int itemSize) {
        if ((dataOffset + itemCount * itemSize) > dataBytes.length) {
            throw new IllegalArgumentException("The tail index of all slices is out of bound of data bytes!");
        }
        this.dataBytes = dataBytes;
        // this.length = (dataOffset + count * size) - totalSize;
        this.totalSize = totalSize;
        this.dataOffset = dataOffset;
        this.itemCount = itemCount;
        this.itemSize = itemSize;
    }

    /**
     * 总的字节数；包含各个子数据片段之间间隔的头部字节
     *
     * @return int
     */
    @Override
    public int getTotalSize() {
        return totalSize;
    }

    /**
     * 包含的子片段的数量
     *
     * @return int
     */
    @Override
    public int getCount() {
        return itemCount;
    }

    /**
     * 返回一个子数据片段
     *
     * @param idx 子数据片段的编号；大于等于 0 ，小于总数 {@link #getCount()}
     * @return {@link BytesSlice}
     */
    @Override
    public BytesSlice getDataSlice(int idx) {
        if (idx < 0 || idx >= itemCount) {
            throw new IllegalArgumentException("The specified idx is out of bound!");
        }
        return new BytesSlice(dataBytes, dataOffset + idx * itemSize, itemSize);
    }

    public BytesSlice getDataSlice(int idx, int length) {
        if (idx < 0 || idx >= itemCount) {
            throw new IllegalArgumentException("The specified idx is out of bound!");
        }
        return new BytesSlice(dataBytes, dataOffset + idx * itemSize, length);
    }

    @Contract("_, _ -> new")
    public static @NotNull FixedBytesSliceArray resolve(@NotNull BytesInputStream bytesStream, int itemSize) {
        int position = bytesStream.getPosition();
        int itemCount = (int) NumberMask.NORMAL.resolveMaskedNumber(bytesStream);
        int dataOffset = bytesStream.getPosition();
        bytesStream.skip(itemCount * itemSize);
        int totalSize = bytesStream.getPosition() - position;
        return new FixedBytesSliceArray(bytesStream.getOriginBytes(), totalSize, dataOffset, itemCount, itemSize);
    }
}
